package com.cse.mvc.models;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.junit.Test;

import com.mutear.ParallelSearcher.utils.IResult;

/**
 * 在该类中 distance 表示搜索结果的排名（相对于单独一个搜索引擎而言）
 * 
 * @author Mutear
 *
 */
public class Result extends IResult {

	/**
	 * 搜索结果的标题
	 */
	private String title;
	/**
	 * 搜索结果的链接
	 */
	private String url;
	/**
	 * 默认 Url 的频次
	 */
	private int freq;
	/**
	 * 不同搜索结果的不同链接及其出现的频次
	 */
	private Map<String, Integer> urls;
	/**
	 * 搜索结果的简介
	 */
	private String summary;
	/**
	 * 搜索出此结果的搜索引擎列表
	 */
	private List<String> engineNames;

	public Result(String title, String url, String summary,
			String defaultEngineName) {
		this.title = title;
		this.url = url;
		this.freq = 1;
		this.urls = new HashMap<String, Integer>();
		this.urls.put(url, 1);
		this.summary = summary;
		this.engineNames = new ArrayList<String>();
		this.engineNames.add(defaultEngineName);
	}

	@Override
	public boolean equal(IResult r2) {
		Result result2 = (Result) r2;
		// 标题相似则 equal
		if (similarTitle(title, result2.title)) {
			return true;
		}
		// 链接相同则 equal
		if (containUrl(result2.getUrl())) {
			return true;
		}
		// 描述相似则 equal，日后添加

		return false;
	}

	/**
	 * 两标题是否相似<br>
	 * 使用最长公共子序列算法<br>
	 * 当最长公共子序列的长度大于较长的标题的长度的一半时，则认为两者相同
	 * 
	 * @param title0
	 * @param title1
	 * @return
	 */
	private boolean similarTitle(String title0, String title1) {
		int len0 = title0.length();
		int len1 = title1.length();
		int maxLen = len0 > len1 ? len0 : len1;
		int[][] value = new int[len0][len1];

		// 求得最长公共子序列长度
		// 初始化数据（第一行与第一列能够明显求出，作为初始数据）
		for(int i = 0; i < len0; i++){
			value[i][0] = same(title0.charAt(i), title1.charAt(0));
			if(value[i][0] == 0 && i > 0){
				value[i][0] = value[i-1][0];
			}
		}
		for(int i = 1; i < len1; i++){
			value[0][i] = same(title0.charAt(0), title1.charAt(i));
			if(value[0][i] == 0 && i > 0){
				value[0][i] = value[0][i-1];
			}
		}
		// 使用动态规划实现递归函数
		// f[1][1] = same(1,1);
		// f[i][j] = max{f[i-1][j-1]+same(i,j),f[i-1][j],f[i][j-1]};
		for(int i = 1; i < len0; i++){
			for(int j = 1; j < len1; j++){
				int v1 = value[i-1][j-1] + same(title0.charAt(i), title1.charAt(j));
				int v2 = value[i-1][j];
				int v3 = value[i][j-1];
				value[i][j] = v1>v2?(v1>v3?v1:v3):(v2>v3?v2:v3);
			}
		}
		
		// 判断最长公共子序列长度是否大于阈值
		if(value[len0-1][len1-1] >= maxLen/2){
			return true;
		}

		return false;
	}
	
	private int same(char c0, char c1){
		if(c0 == c1){
			return 1;
		}
		else{
			return 0;
		}
	}

	public void addEngine(String engineName) {
		this.engineNames.add(engineName);
	}

	public String getTitle() {
		return title;
	}

	public String getUrl() {
		return url;
	}

	public String getSummary() {
		return summary;
	}

	public List<String> getEngineNames() {
		return engineNames;
	}

	public void setUrl(String url) {
		this.url = url;
	}
	
	/**
	 * 添加 Url
	 * @param url
	 */
	public void addUrl(String url){
		int i = urls.getOrDefault(url, 0);
		urls.put(url, i + 1);
		
		// 将默认 Url 设置为频次最高的 Url
		for(String str : urls.keySet()){
			int num = urls.get(str);
			if(num > freq){
				freq = num;
				this.url = str;
			}
		}
	}
	
	/**
	 * 判断是否包含某个 Url
	 * @param url
	 * @return
	 */
	public boolean containUrl(String url){
		for(String str : urls.keySet()){
			if(str.equalsIgnoreCase(url)){
				return true;
			}
		}
		
		return false;
	}
	
}
